﻿using System;

namespace Silver3D.Graphics
{
    /// <summary>
    /// Designed to be called when a SceneObject is being detached from the host Scene.
    /// </summary>
    /// <param name="sender"></param>
    public delegate void ObjectDetachedHandler(SceneObject sender);

    /// <summary>
    /// A SceneObject is an object that belongs to a (single) Scene.
    /// </summary>
    public class SceneObject : Animatable
    {
        /// <summary>
        /// The Scene instance that owns this SceneObject.
        /// </summary>
        public Scene Scene { get; internal set; }

        /// <summary>
        /// The unique identifier for this SceneObject.
        /// </summary>
        public string Id { get; internal set; }

        /// <summary>
        /// Event invoked when this SceneObject is detached from the Scene.
        /// </summary>
        public event ObjectDetachedHandler Detached;

        /// <summary>
        /// Number of objects referencing this SceneObject.
        /// </summary>
        public int ReferenceCount
        {
            get
            {
                if (Detached == null) return 0;
                return Detached.GetInvocationList().Length;
            }
        }

        /// <summary>
        /// Determines if the object is currently detached from the Scene.
        /// Most operations on a detached object are forbidden.
        /// </summary>
        public bool IsDetached
        {
            get { return Scene == null; }
        }

        /// <summary>
        /// Constructs a SceneObject.
        /// </summary>
        /// <param name="scene">The parent Scene. Must be non-null.</param>
        /// <param name="desiredId">The object's desired ID. The ID may be modified by the Scene to ensure uniqueness.</param>
        public SceneObject(Scene scene, string desiredId)
        {
            if (scene == null)
                throw new ArgumentNullException("scene");

            scene.RegisterObject(this, desiredId);
        }

        /// <summary>
        /// Detaches the object from the parent Scene.
        /// </summary>
        public virtual void Detach()
        {
            if (Detached != null)
            {
                Detached(this);
                Detached = null;
            }
        }
    }

    public class NamedSceneObject : SceneObject
    {
        public string Name { get; set; }

        public NamedSceneObject(Scene scene, string desiredId)
            : base(scene, desiredId)
        {
            Name = string.Empty;
        }

        public NamedSceneObject(Scene scene, string desiredId, string name)
            : base(scene, desiredId)
        {
            Name = name ?? string.Empty;
        }
    }
}
